package com.wxlsoft.excel.convert;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.LinkedList;
import java.util.List;

import javax.swing.JProgressBar;

import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelReader;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.enums.WriteDirectionEnum;
import com.alibaba.excel.read.metadata.ReadSheet;
import com.alibaba.excel.write.builder.ExcelWriterSheetBuilder;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.fill.FillConfig;
import com.alibaba.excel.write.metadata.fill.FillWrapper;
import com.wxlsoft.excel.convert.handlers.IndexCellWriteHandler;
import com.wxlsoft.excel.convert.handlers.ServiceEmptyOutsWriteHandler;
import com.wxlsoft.excel.convert.handlers.ServicePackageParser;
import com.wxlsoft.excel.convert.listeners.CommonPackageListener;
import com.wxlsoft.excel.convert.listeners.IndexListener;
import com.wxlsoft.excel.convert.listeners.ModifyHistoryListener;
import com.wxlsoft.excel.convert.listeners.ServicePackageListener;
import com.wxlsoft.excel.convert.model.BasePackageRecord;
import com.wxlsoft.excel.convert.model.IndexPackage;
import com.wxlsoft.excel.convert.model.IndexRecord;
import com.wxlsoft.excel.convert.model.IndexTo;
import com.wxlsoft.excel.convert.model.ModifyHistory;
import com.wxlsoft.excel.convert.model.ServicePackage;
import com.wxlsoft.excel.convert.model.SheetDataConvertCollector;
import com.wxlsoft.excel.core.AbstractProcessor;
import com.wxlsoft.ui.ProgressController;

import lombok.extern.slf4j.Slf4j;

@Slf4j
public class DataConvertProcessor extends AbstractProcessor {

	private final SheetDataConvertCollector collector = new SheetDataConvertCollector();

	private final String from;
	
	private final String to;
	
	private final String tmp;
	
	public DataConvertProcessor(String from, String to, String tmp) {
		this.from = from;
		long millis = System.currentTimeMillis();
		this.to = String.format(to.toString(), millis);
		this.tmp = String.format(tmp.toString(), millis);
	}
	
	// 写出到 excel 中
	@Override
	protected void write(JProgressBar progress) {
        try (ExcelWriter excelWriter = EasyExcel.write(to).withTemplate(tmp).build()) {
        	// 修订页
        	WriteSheet modifyTable = EasyExcel.writerSheet(0).build();
        	excelWriter.fill(collector.getModifys(), modifyTable);
        	
        	FillConfig fillConfig = FillConfig.builder()
        			.forceNewRow(true)
        			.direction(WriteDirectionEnum.VERTICAL)
        			.build();
        	
        	// INDEX页
            WriteSheet indexTable = EasyExcel.writerSheet(1)
            		.registerWriteHandler(new IndexCellWriteHandler()).build();
            IndexPackage ip = collector.getIndexPackage();
            excelWriter.fill(ip.getIndexs(), fillConfig, indexTable);
            excelWriter.fill(ip.getNote(), fillConfig, indexTable);
            
            // 公共报文头
            WriteSheet headTable = EasyExcel.writerSheet(4).build();
            ServicePackage head = collector.getHead();
            excelWriter.fill(new FillWrapper("input", head.getInputs()), fillConfig, headTable);
            excelWriter.fill(new FillWrapper("output", head.getOutputs()), fillConfig, headTable);
            
            // service 模板输出
            List<ServicePackage> services = collector.getServices();
            for (ServicePackage service : services) {
            	ExcelWriterSheetBuilder serviceSheet = EasyExcel.writerSheet(service.getSheetName());
            	if (ServicePackageParser.fillEmptyOutput(service.getOutputs())) {
            		serviceSheet.registerWriteHandler(new ServiceEmptyOutsWriteHandler());
            	}
            	WriteSheet serviceTable = serviceSheet.build();
            	excelWriter.fill(service.getHead(), serviceTable);
            	excelWriter.fill(new FillWrapper("input", service.getInputs()), fillConfig, serviceTable);
            	excelWriter.fill(new FillWrapper("output", service.getOutputs()), fillConfig, serviceTable);
            	ProgressController.writeProgress(progress);
            }
        }
        
	}

	/**
	 * 按顺序读取原信息
	 */
	@Override
	protected void read(JProgressBar progress) {
		try (ExcelReader read = EasyExcel.read(from).build()) {
			
			ReadSheet modify = EasyExcel.readSheet("修订历史")
					.headRowNumber(1)
					.head(ModifyHistory.class)
					.registerReadListener(new ModifyHistoryListener("修订历史", progress, collector))
					.build();
			ProgressController.readProgress(progress);
			
			ReadSheet index = EasyExcel.readSheet("INDEX")
					.headRowNumber(1)
					.head(IndexRecord.class)
					.registerReadListener(new IndexListener("INDEX", progress, collector))
					.build();
			
			
			ReadSheet common = EasyExcel.readSheet("公共报文头")
					.headRowNumber(4)
					.head(BasePackageRecord.class)
					.registerReadListener(new CommonPackageListener("公共报文头", progress, collector))
					.build();
			
			read.read(modify, index, common);
		}
		
		// 迭代 index 清单
		try (ExcelReader read = EasyExcel.read(from).build()) {
			final List<ReadSheet> sheets = new LinkedList<>();
			
			for (IndexTo index : collector.getIndexPackage().getIndexs()) {
				ReadSheet sheet = EasyExcel.readSheet(index.getTradeCode())
						.headRowNumber(0)
						.head(BasePackageRecord.class)
						.registerReadListener(new ServicePackageListener(index.getInterfaceId(), index.toBooleanStandard(), progress, collector))
						.build();
				sheets.add(sheet);
			}
			read.read(sheets);
		}
	}
	
	/**
	 * 准备模板文件
	 */
	@Override
	protected void copyTmp(JProgressBar progress) {
		InputStream template = this.getClass().getResourceAsStream("/template.xlsx");
		try (OutputStream out = new FileOutputStream(tmp); Workbook sheets = new XSSFWorkbook(template)) {
			List<IndexTo> indexs = collector.getIndexPackage().getIndexs();
			for (IndexTo index : indexs) {
				Sheet newSheet = sheets.cloneSheet(5);
				int sheetIndex = sheets.getSheetIndex(newSheet);
				sheets.setSheetName(sheetIndex, index.getInterfaceId());
			}
			
			sheets.removeSheetAt(5);
			int numberOfSheets = sheets.getNumberOfSheets();
			sheets.setSheetOrder("MAPPING_SLA", numberOfSheets - 1);
			
			sheets.write(out);
		} catch (Exception e) {
			log.error(e.getMessage());
		}
	}

	/**
	 * 清理临时文件
	 */
	@Override
	protected void cleanTmp(JProgressBar progress) {
		new File(tmp).delete();
	}		

}
